{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "thorough-brake",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from scipy.optimize import minimize\n",
    "import pandas as pd\n",
    "from IPython.display import clear_output\n",
    "import copy\n",
    "import matplotlib.pyplot as plt\n",
    "import time\n",
    "\n",
    "from FBSM_library import FBSM, Objective_Functional\n",
    "from DM_library import DM\n",
    "from InitProblem_library import RKM_Dyn_System\n",
    "from Support_library import Define_Arguments, Obj_Functional_Iterations, Show_Control, Plot_Dynamics\n",
    "from Transition_Matrices_Bank import P_ass_strict_3, P_ass_strict_confidence_3, P_ass_smooth_3, P_ass_smooth_5"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c696fe99-f2dc-4196-a28f-dcb1091360c7",
   "metadata": {},
   "source": [
    "# m=3, M=1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a2caff8-95d2-4901-ab1a-abc8869ee2d0",
   "metadata": {},
   "source": [
    "## Set parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bdd69a18-3931-4d8a-8c5a-c6ac052482be",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = 1  # the number of types of ordinary agents \n",
    "\n",
    "m = 3  # the number of elements in the opinion alphabet\n",
    "n = 0.6  # the fraction of ordinary agents in the system  \n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the transition matrix\n",
    "\n",
    "Transition_Matrices = {}\n",
    "\n",
    "# These transition matrices outline how ordinary agents influence each other \n",
    "\n",
    "for i in range(M):\n",
    "    for j in range(M):\n",
    "        Transition_Matrices[f'{i}-{j}'] = P_ass_strict_3\n",
    "\n",
    "# These transition matrices outline how stubborn agents influence ordinary agents \n",
    "        \n",
    "for i in range(M):\n",
    "    Transition_Matrices[f'{i}-{M}'] = P_ass_strict_3\n",
    "    \n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the grid\n",
    "\n",
    "Tau_0 = 0\n",
    "Tau_1 = 65\n",
    "Step = 1\n",
    "Grid = np.arange(Tau_0, Tau_1+Step, Step)\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Define the objective functional\n",
    "\n",
    "K = 1\n",
    "\n",
    "v = np.array([2, 1, 0])  # the opinion weights (terminal)\n",
    "w = K*v  # the opinion weights (integral)\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the starting point ( y_{0} )\n",
    "\n",
    "y_0 = np.array([[0.1], \n",
    "                [0.3], \n",
    "                [0.2]])\n",
    "\n",
    "\n",
    "n_types = [0.6]\n",
    "\n",
    "    \n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Create a dictionary of arguments\n",
    "\n",
    "Arguments = Define_Arguments(\n",
    "                             #A, b, c, s, \n",
    "                             M, m, \n",
    "                             n, \n",
    "                             Transition_Matrices, \n",
    "                             Step, Grid, Tau_0, Tau_1, \n",
    "                             w, v, \n",
    "                             n_types)\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the starting control guess ( u_{0} (\\tau) )\n",
    "\n",
    "u_basic = np.array([[0.4], \n",
    "                    [0], \n",
    "                    [0]])\n",
    "\n",
    "u_t_0 = []\n",
    "\n",
    "for i in range(len(Grid)-1):\n",
    "    \n",
    "    u_t_0.append(u_basic) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "369de492-26df-47d2-8967-d65fc78faa42",
   "metadata": {},
   "source": [
    "## Run the direct method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc61d184-e1a2-46b1-b79c-376d02b9e13f",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "t_start = time.time()\n",
    "\n",
    "u_t = DM(y_0, u_t_0, Arguments)\n",
    "\n",
    "t_end = time.time()\n",
    "\n",
    "t_elapsed = round((t_end - t_start) / 60, 1)\n",
    "\n",
    "t_elapsed_sec = round((t_end - t_start), 1)\n",
    "\n",
    "print(f'Time elapsed: {t_elapsed} min / {t_elapsed_sec} sec')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cc021ab-9fe9-4b9a-a447-d06ed0dbc9a1",
   "metadata": {},
   "source": [
    "## Show results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "609c6344-ed57-442b-a48a-c18efc8c8062",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Show the control function obtained\n",
    "\n",
    "print('')\n",
    "\n",
    "print('The control function obtained:')\n",
    "\n",
    "print(Show_Control(u_t))\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Calculate the value of the objective functional\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t, Arguments, 1)\n",
    "\n",
    "value = Objective_Functional(y_t, Arguments)\n",
    "\n",
    "print('')\n",
    "\n",
    "print('The value of the objective functional provided by this control:', round(value[0]+value[1], 3))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60b2dc9e-4a2c-4fe6-9968-458e0eeaefab",
   "metadata": {},
   "source": [
    "## Run the FBS method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "07f74567-2571-4a49-988f-926fe28d1dd3",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_start = time.time()\n",
    "\n",
    "(u_t_estimations, Functional_estimations, Status) = FBSM(y_0, u_t_0, Arguments)\n",
    "\n",
    "t_end = time.time()\n",
    "\n",
    "t_elapsed = round((t_end - t_start) / 60, 1)\n",
    "\n",
    "t_elapsed_sec = round((t_end - t_start), 1)\n",
    "\n",
    "print(f'Time elapsed: {t_elapsed} min / {t_elapsed_sec} sec')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22b39d89-b3d8-45f4-993a-5910e4443325",
   "metadata": {},
   "source": [
    "## Show results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc1dd92a-8865-4781-aa0a-71cbfd859e48",
   "metadata": {},
   "outputs": [],
   "source": [
    "print('The last approximation:')\n",
    "\n",
    "Show_Control(u_t_estimations[-1])\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "print('')\n",
    "print('The best approximation:')\n",
    "\n",
    "sums = []\n",
    "\n",
    "for i in Functional_estimations:\n",
    "    sums.append(i[0]+i[1])\n",
    "\n",
    "Show_Control(u_t_estimations[np.argmin(sums)])\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[-1], Arguments, 1)  # last approximation\n",
    "value = Objective_Functional(y_t, Arguments)\n",
    "print('The value of the objective functional provided by the last approximation:', round(value[0]+value[1], 3))\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[np.argmin(sums)], Arguments, 1)  # the best approximation\n",
    "value = Objective_Functional(y_t, Arguments)\n",
    "print('')\n",
    "print('The value of the objective functional provided by the best approximation:', round(value[0]+value[1], 3))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "951a3f4c-98b6-4fb8-80fc-d1735fce56ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Show the dynamics of the objective functional across iterations of the FBS method\n",
    "\n",
    "FS = 15\n",
    "LW = 2\n",
    "MS = 5\n",
    "MEW = 2\n",
    "LS = 10\n",
    "\n",
    "Obj_Functional_Iterations(Functional_estimations, FS, LW, MS, MEW, LS)\n",
    "\n",
    "# Plot the corresponding dynamics of state variables (the last approximation)\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[-1], Arguments, 1)  \n",
    "\n",
    "LW = 1\n",
    "FS = 15\n",
    "\n",
    "Plot_Dynamics(y_t, LW, FS, Arguments)\n",
    "\n",
    "# Plot the corresponding dynamics of state variables (the best approximation)\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[np.argmin(sums)], Arguments, 1)  \n",
    "\n",
    "LW = 1\n",
    "FS = 15\n",
    "\n",
    "Plot_Dynamics(y_t, LW, FS, Arguments)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9882f320-1ba0-44c4-8559-d15287c7f054",
   "metadata": {},
   "source": [
    "# m = 5, M = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea722b2c-80a3-4393-ab05-c33efac9b363",
   "metadata": {},
   "source": [
    "## Set parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21103294-0c19-4086-8314-e039be25916f",
   "metadata": {},
   "outputs": [],
   "source": [
    "M = 1  # the number of types of ordinary agents \n",
    "\n",
    "m = 5  # the number of elements in the opinion alphabet\n",
    "n = 0.6  # the fraction of ordinary agents in the system  \n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the transition matrix\n",
    "\n",
    "Transition_Matrices = {}\n",
    "\n",
    "# These transition matrices outline how ordinary agents influence each other \n",
    "\n",
    "for i in range(M):\n",
    "    for j in range(M):\n",
    "        Transition_Matrices[f'{i}-{j}'] = P_ass_smooth_5\n",
    "\n",
    "# These transition matrices outline how stubborn agents influence ordinary agents \n",
    "        \n",
    "for i in range(M):\n",
    "    Transition_Matrices[f'{i}-{M}'] = P_ass_smooth_5\n",
    "    \n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the grid\n",
    "\n",
    "Tau_0 = 0\n",
    "Tau_1 = 10\n",
    "Step = 1\n",
    "Grid = np.arange(Tau_0, Tau_1+Step, Step)\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Define the objective functional\n",
    "\n",
    "K = 1\n",
    "\n",
    "v = np.array([2, 1, 0])  # the opinion weights (terminal)\n",
    "w = K*v  # the opinion weights (integral)\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the starting point ( y_{0} )\n",
    "\n",
    "y_0 = np.array([[0.1], \n",
    "                [0.4], \n",
    "                [0.1], \n",
    "                [0], \n",
    "                [0]])\n",
    "\n",
    "\n",
    "n_types = [0.6]  \n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Create a dictionary of arguments\n",
    "    \n",
    "Arguments = Define_Arguments(M, m, \n",
    "                             n, \n",
    "                             Transition_Matrices, \n",
    "                             Step, Grid, Tau_0, Tau_1, \n",
    "                             w, v, \n",
    "                             n_types)\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Initialize the starting control guess ( u_{0} (\\tau) )\n",
    "\n",
    "u_basic = np.array([[0.4], \n",
    "                    [0], \n",
    "                    [0], \n",
    "                    [0], \n",
    "                    [0]])\n",
    "\n",
    "u_t_0 = []\n",
    "\n",
    "for i in range(len(Grid)-1):\n",
    "    \n",
    "    u_t_0.append(u_basic) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b76342f0-faf2-43cc-a967-86652779ba27",
   "metadata": {},
   "source": [
    "## Run the direct method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "513bffd0-666f-4386-9145-9a69324bddd4",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_start = time.time()\n",
    "\n",
    "u_t = DM(y_0, u_t_0, Arguments)\n",
    "\n",
    "t_end = time.time()\n",
    "\n",
    "t_elapsed = round((t_end - t_start) / 60, 1)\n",
    "\n",
    "print(f'Time elapsed: {t_elapsed} min')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4c40c16-3dac-475e-884f-3dac0463da37",
   "metadata": {},
   "source": [
    "## Show results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d9ced59-1d53-4fd5-b0cf-d56480e3bf22",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Show the control function obtained\n",
    "\n",
    "print('')\n",
    "\n",
    "print('The control function obtained:')\n",
    "\n",
    "print(Show_Control(u_t))\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "# Calculate the value of the objective functional\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t, Arguments, 1)\n",
    "\n",
    "value = Objective_Functional(y_t, Arguments)\n",
    "\n",
    "print('')\n",
    "\n",
    "print('The value of the objective functional provided by this control:', round(value[0]+value[1], 3))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bccc612-70eb-426a-9e05-ca8294868d49",
   "metadata": {},
   "source": [
    "## Run the FBS method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a40211ae-eec6-4941-9b98-32138d27dcc3",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_start = time.time()\n",
    "\n",
    "(u_t_estimations, Functional_estimations, Status) = FBSM(y_0, u_t_0, Arguments)\n",
    "\n",
    "t_end = time.time()\n",
    "\n",
    "t_elapsed = round((t_end - t_start) / 60, 1)\n",
    "\n",
    "t_elapsed_sec = round((t_end - t_start), 1)\n",
    "\n",
    "print(f'Time elapsed: {t_elapsed} min / {t_elapsed_sec} sec')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b1b493df-5bf5-4eb5-a3ab-6d7f6120ee59",
   "metadata": {},
   "source": [
    "## Show results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef2f8c6a-2198-48da-96a9-fa8c7d25cc32",
   "metadata": {},
   "outputs": [],
   "source": [
    "print('The last approximation:')\n",
    "\n",
    "Show_Control(u_t_estimations[-1])\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "print('')\n",
    "print('The best approximation:')\n",
    "\n",
    "sums = []\n",
    "\n",
    "for i in Functional_estimations:\n",
    "    sums.append(i[0]+i[1])\n",
    "\n",
    "Show_Control(u_t_estimations[np.argmin(sums)])\n",
    "\n",
    "#---------------------------------------------------------------------------\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[-1], Arguments, 1)  # last approximation\n",
    "value = Objective_Functional(y_t, Arguments)\n",
    "print('The value of the objective functional provided by the last approximation:', round(value[0]+value[1], 3))\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[np.argmin(sums)], Arguments, 1)  # the best approximation\n",
    "value = Objective_Functional(y_t, Arguments)\n",
    "print('')\n",
    "print('The value of the objective functional provided by the best approximation:', round(value[0]+value[1], 3))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80ef747a-b5bf-4fc9-8f6f-c02bd99680ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Show the dynamics of the objective functional across iterations of the FBS method\n",
    "\n",
    "FS = 15\n",
    "LW = 2\n",
    "MS = 5\n",
    "MEW = 2\n",
    "LS = 10\n",
    "\n",
    "Obj_Functional_Iterations(Functional_estimations, FS, LW, MS, MEW, LS)\n",
    "\n",
    "# Plot the corresponding dynamics of state variables (the last approximation)\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[-1], Arguments, 1)  \n",
    "\n",
    "LW = 1\n",
    "FS = 15\n",
    "\n",
    "Plot_Dynamics(y_t, LW, FS, Arguments)\n",
    "\n",
    "# Plot the corresponding dynamics of state variables (the best approximation)\n",
    "\n",
    "y_t = RKM_Dyn_System(y_0, u_t_estimations[np.argmin(sums)], Arguments, 1)  \n",
    "\n",
    "LW = 1\n",
    "FS = 15\n",
    "\n",
    "Plot_Dynamics(y_t, LW, FS, Arguments)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
